﻿using System;
using System.Collections.Generic;
using GeoRef;
using TripLOA.WebService.Serializable;
using TripLOA.WebService.Wrappers;

namespace TripLOA.WebService
{
    /// <summary>
    /// This class defines web-methods for georeferencetion.
    /// </summary>
    public class GeoRefCore : WsCore
    {
        private static GeoRefCore istance = null;

        #region GeoRefCore Constructors

        /// <summary>
        /// Parameterless Constructor
        /// </summary>
        private GeoRefCore() { }

        /// <summary>
        /// Static Constructor
        /// </summary>
        /// <returns>A new istance of GeoRefCore</returns>
        public static GeoRefCore Istance()
        {
           if(istance==null) {
               istance = new GeoRefCore();
            }
            return istance;
        }

        #endregion

        #region GeoRef Methods
        // DA COMPLETARE
        /// <summary>
        /// </summary>
        /// <returns>A serializable WSGeoTrip object</returns>
        public WSGeoTrip getGeoTrip()
        {
            GeoTrip gt = this.createTestGeoTrip();
            WSGeoTrip wsgt = new WSGeoTrip("ok", gt);
            return wsgt;
        }

        /// <summary>
        /// Default geoCoding method. Get the geographic coordinates of the given location
        /// </summary>
        /// <param name="location">string of the location</param>
        /// <returns>A serializable WSGeoLoc object</returns>
        public WSGeoLoc geoCoding(string location)
        {
            GeoQuery gq = new GeoQuery();
            WSGeoLoc wsgl = new WSGeoLoc("ok");
            wsgl.Payload = gq.geoCoding(location);
            return wsgl;
        }

        /// <summary>
        /// Overload of geoCoding method. Get the geographic coordinaes of a more specific location.
        /// </summary>
        /// <param name="state"></param>
        /// <param name="city"></param>
        /// <param name="road"></param>
        /// <returns>A serializable WSGeoLoc object</returns>
        public WSGeoLoc geoCoding(string state, string city, string road)
        {
            GeoQuery gq = new GeoQuery();
            List<GeoLoc> gl;
            if (road != null)
            {
                gl = gq.geoCoding(state, city, road);
            }
            else if (city != null)
            {
                gl = gq.geoCoding(state, city);
            }
            else
            {
                gl = gq.geoCoding(state); //LOCATION
            }
            WSGeoLoc wsgl = new WSGeoLoc("ok");
            wsgl.Payload = gl;
            return wsgl;
        }

        /// <summary>
        /// Transforms geographic coordinates in a geographic location
        /// </summary>
        /// <param name="lat">latitude</param>
        /// <param name="lng">longitude</param>
        /// <returns>A serializable WSGeoLoc object</returns>
        public WSGeoLoc reverseGeoCoding(double lat, double lng)
        {
            GeoQuery gq = new GeoQuery();
            WSGeoLoc wsgl = new WSGeoLoc("ok");
            GeoLoc gl = null;
            try
            {
                gl = gq.reverseGeoCoding(lat, lng);
            }
            catch (Exception)
            {
                
                throw;
            }
            wsgl.Payload.Add(gl);
            return wsgl;
        }

        #endregion

        #region Private Test Methods

        private Random r = new Random();

        private TripInfo createTestTrip()
        {
            //Test Places
            List<string> places = new List<string>();
            places.Add("Pisa");
            places.Add("Firenze");
            places.Add("Lucca");
            places.Add("Siena");
            places.Add("Prato");
            places.Add("Pistoia");
            places.Add("Bologna");
            places.Add("Roma");

            //Test Departure Dates
            List<DateTime> startDates = new List<DateTime>();
            startDates.Add(new DateTime(2008, 04, 10));
            startDates.Add(new DateTime(2008, 04, 12));
            startDates.Add(new DateTime(2008, 04, 14));
            startDates.Add(new DateTime(2008, 04, 15));
            startDates.Add(new DateTime(2008, 04, 18));
            startDates.Add(new DateTime(2008, 04, 21));


            string departure = places[(r.Next(places.Count))];
            string arrival = places[(r.Next(places.Count))];
            TripInfo ti = new TripInfo() { ID = r.Next(1001), Departure = departure, Arrival = arrival, DepartureDate = startDates[r.Next(startDates.Count)],  EstimatedBudget = (byte)(r.Next(11)) };
            return ti;
        }

        // <GeoRef>
        static int idTrip = 0;
        // </GeoRef>

        private GeoTrip createTestGeoTrip()
        {
            //<GeoRef>
            GeoTrip trip;
            GeoLoc start;
            GeoLoc end;
            List<GeoLoc> l = new List<GeoLoc>();
            GeoQuery query = new GeoQuery();

            if (idTrip % 2 == 0)
            {
                start = new GeoLoc("43.676830,10.690780", "San Donato", "Casa mia");
                end = new GeoLoc("43.72055948722688,10.407872200012207", "Università", "Arrivato!");
                l.Add(new GeoLoc("43.681630,10.562980", "prr", ""));
                trip = new GeoTrip(start, end, l);
                GeoLoc nextRouteEnd = query.geoCoding("italy", "rosignano marittimo")[0];
                GeoRoute nextTappa = new GeoRoute(end, nextRouteEnd);
                nextTappa.Vehicle = VehicleType.plane;
                nextTappa.InsertViaPoint(query.geoCoding("italy", "castiglioncello, livorno")[0]);
                nextTappa.InsertViaPoint(query.geoCoding("italy", "santa luce")[0]);
                trip.AddRoute(nextTappa);
            }
            else
            {
                start = query.geoCoding("italy", "pisa", "via di pratale")[0];
                start.Description = "Fuggire dall'università";
                end = query.geoCoding("italy", "Firenze")[0];
                end.Description = "La culla del rinascimento!";
                l.Add(query.geoCoding("italy", "Prato")[0]);
                trip = new GeoTrip(start, end, l);
            }

            trip.UpdatePath();
            idTrip++;
            return trip;

            // </GeoRef>
        }

        public static GeoTrip CreateGeoTrip(String departure, String arrival)
        {
            GeoQuery gq = new GeoQuery();
            GeoLoc startPoint = gq.geoCoding(departure)[0];
            GeoLoc endPoint = gq.geoCoding(arrival)[0];
            GeoTrip gt = new GeoTrip(startPoint, endPoint);
            return gt;
        }
        #endregion
    }
}
